/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __GUI_COMPONENT_H__
#define __GUI_COMPONENT_H__

#pragma once

#include "guidefaults.h"
#include "geom/Vector.h"
#include <string>
#include <vector>
#include "IGUIRenderer.h"
#include "IActionListener.h"
#include "IMouseListener.h"
#include "IFont.h"

namespace gui {

/// The types of the GUI elements
enum eGUIType {
	GUI_COMPONENT = 0,
	GUI_BUTTON,
	GUI_CANVAS,
	GUI_CHECKBOX,
	GUI_DIALOG,
	GUI_DROPDOWN,
	GUI_FRAME,
	GUI_LABEL,
	GUI_LIST,
	GUI_MENU,
	GUI_MENUITEM,
	GUI_SHELL,
	GUI_TABLE,
	GUI_TABLEITEM,
	GUI_TEXTBOX,
	GUI_SLIDER,
	GUI_RADIOBUTTON,
	GUI_BUTTONGROUP
};

/**
 * \ingroup coreGUI
 *
 * The GUI Component class.<br>
 * Base class for all GUI elements.
 *
 * \date 03-28-2007
 *
 * \author juckel
 * \author dennis
 * 
 * \todo Add images for mouse clicked event. 
 * \todo Draw the images, if they exist instead of the default rendering.
 * \todo Remove ifont.h from gui and build a better font class
 *
 */
class GUI_EXPORT Component
{
public:
	Component();
	virtual ~Component();

	void clearAll();

	/// Set the dimension of the GUI element
	virtual void setDimension(int x, int y, int w, int h);

	/// positions the component in the center
	virtual void centering();

	/// Set the height and width of the GUI element
	virtual void setSize(int w, int h);

	/// Set the position of the GUI element as two float values
	void setPosition(int x, int y);

	/// Set the position of the GUI element as a 2D int vector
	void setPosition(const math::Vector2i &position);

	/// Return the position of the GUI element as a 2D int vector
	const math::Vector2i& getPosition() const;

	/// Return the size of the component
	const math::Vector2i& getSize() const;

	/// Return the width of the GUI element
	const int getWidth() const { return vDim.x; }

	/// Return the height of the GUI element
	const int getHeight() const { return vDim.y; }

	/// Return the x position of the GUI element
	const int getX() const { return vPos.x; }

	/// Return the y position of the GUI element
	const int getY() const { return vPos.y; };

	/// Set a component so that it is visible
	void setVisible(bool value);

	/// Indicate if a component is visible. Default is true
	bool isVisible() const;

	/// Process movement of the mouse
	virtual bool processMouse(int _x, int _y, int _z, int button);

	/// Add an ActionListener to this component. All ActionListeners will be called, when an event occurred.
	/// An action event is triggered upon clicking the component.
	void addActionListener( IActionListener *actionListener );

	/// Remove an ActionListener from this component
	void removeActionListener( IActionListener *actionListener );

	/// Add a MouseListener to this component. All MouseListeners will be called, when an mouse event occurs.
	/// Mouse events include MouseEnterEvent, MouseLeaveEvent, MousePressedEvent
	void addMouseListener( IMouseListener* mouseListener );

	/// Remove a MouseListener from this component
	void removeMouseListener( IMouseListener* mouseListener );

	/// Add a sub component to this component
	void add(Component *comp);

	/// Remove a sub component from this component
	void remove(Component *comp);

	/// Bring this component to front
	void bringToFront();

	/// Set the color of the component
	void setBackColor(float r, float g, float b, float a);

	/// Set the color the border of the component
	void setBorderColor(float r, float g, float b, float a);

	/// Set the color of the displayed text
	void setTextColor(float r, float g, float b, float a);

	void setEnabled(bool value);

	void setBackground(ITexture *texture);

	virtual void setFont(IFont* pFont);

	/// Set a background image for an disabled element
	void setDisabledBackground(ITexture *texture);

	virtual void update() {};
	/// The draw function of the component. Needs to be implemented by rendering specific methods
	virtual void draw() = 0;

	/// Windows message handling
	virtual void winMsgProc( UINT msg, WPARAM wParam, LPARAM lParam );

	/// Get the position in screen-coordinates
	math::Vector2i getAbsolutePosition();

	/// Return of the type of the GUI element
	virtual inline const int getGUIType() const { return GUI_COMPONENT; }

	/// added 25.5.07
	gui::Component* getParent();

	static void ExecUpdate();

	typedef std::vector<Component*>       comp_list;
	typedef std::vector<std::string>      gui_list;
	typedef std::vector<IActionListener*> al_list;
	typedef std::vector<IMouseListener*>  ml_list;

	comp_list* getChildren() { return &components; };

protected:
	static bool s_bDrawChanges;

	bool m_bActionPerformed;

	/// Function called when an action occured
	virtual void performAction(int x, int y, int button);
	/// Set the focus of the component
	virtual void setFocus() {};
	/// Unset the focus of the component
	virtual void unsetFocus() {};
	/// Function called upon entering with the mouse
	virtual void onMouseEntered(const MouseEvent &me);
	/// Function called upon leaving with the mouse
	virtual void onMouseLeft(const MouseEvent &me);
	/// Function called upon pressing a mouse button
	virtual void onMousePressed(const MouseEvent &me);
	/// Function called upon releasing a pressed mouse button
	virtual void onMouseReleased(const MouseEvent &me);
	virtual void onMouseDragged(const MouseEvent &me);
	/// Draws all sub components	
	virtual void drawElements();
	/// Sets the parent of this component
	void setParent(Component *parent);
	/// Calls all registered ActionListener when an event has occurred
	void execFunction(const ActionEvent &actionEvent);

	int iLastButton;				///< The last pressed button
	static IGUIRenderer *pRenderer;	///< A pointer to the renderer
	static Component *activeComponent;

	comp_list components;			///< The list containing all sub components
	Component *pParent;				///< The parent component

	math::Vector2i vPos;			///< The relative position to the parent component
	math::Vector2i vRealPos;		///< The real position in actual screen coordinates

	math::Vector2i vDim;			///< The dimension of the component
	math::Vector2i vOffset;			///< The text offset to the border of the component

	bool bMouseEntered;				///< Indicates if the mouse has entered the component
	bool bVisible;					///< Indicates if the component is visible

	bool bEnabled;					///< Indicates if the component is enabled

	math::Vector4 vBorderColor;		///< The color of the border
	math::Vector4 vTextColor;		///< The color of the text
	math::Vector4 vBackColor;		///< The color of the background

	al_list vActionListeners;		///< The list of registered action listeners
	ml_list vMouseListeners;		///< The list of registered mouse listeners
	ml_list::iterator mliter;		///< the mouse listener iterator

	IFont* font;					///< A pointer to the font instance
	int iRowSize;					///< The size of one text row

	ITexture *pTexture;
	ITexture *pDisabledTexture;
};

} // namespace

#endif

